

#include "config.h"
#include <string.h>
#include <time.h>
#include <gdk/gdkkeysyms.h>
#include <amanita/aVector.h>
#include <amanita/net/aHttp.h>

#include "Main.h"
#include "Page.h"
#include "InstallDlg.h"
#include "LoginDlg.h"
#include "ProfileDlg.h"
#include "TextPage.h"
#include "astro/HoroscopeChartPage.h"
#include "astro/PlanetsDlg.h"
#include "tarot/TarotDivinationDlg.h"

/*
#include "../data/images/icons/mantichora16.xpm"
#include "../data/images/icons/mantichora32.xpm"
#include "../data/images/icons/mantichora48.xpm"
#include "../data/images/icons/mantichora64.xpm"
*/

MainFrame app;


int main(int argc,char *argv[]) {
	gtk_init(&argc,&argv);

	gtk_rc_parse_string (
		"style \"tab-close-button-style\"\n"
		"{\n"
		"  GtkWidget::focus-padding = 0\n"
		"  GtkWidget::focus-line-width = 0\n"
		"  xthickness = 0\n"
		"  ythickness = 0\n"
		"}\n"
		"widget \"*.tab-close-button\" style \"tab-close-button-style\"");

	if(!g_thread_supported()) g_thread_init(0);
	app.init(argc,argv);
	gtk_main();
	return 0;
}


enum {
	KEY_CONTROL_MASK				= GDK_CONTROL_MASK,
	KEY_ALT_MASK					= GDK_MOD1_MASK,
	KEY_a								= GDK_KEY_a,
	KEY_b								= GDK_KEY_b,
	KEY_c								= GDK_KEY_c,
	KEY_d								= GDK_KEY_d,
	KEY_e								= GDK_KEY_e,
	KEY_f								= GDK_KEY_f,
	KEY_g								= GDK_KEY_g,
	KEY_h								= GDK_KEY_h,
	KEY_i								= GDK_KEY_i,
	KEY_j								= GDK_KEY_j,
	KEY_k								= GDK_KEY_k,
	KEY_l								= GDK_KEY_l,
	KEY_m								= GDK_KEY_m,
	KEY_n								= GDK_KEY_n,
	KEY_o								= GDK_KEY_o,
	KEY_p								= GDK_KEY_p,
	KEY_q								= GDK_KEY_q,
	KEY_r								= GDK_KEY_r,
	KEY_s								= GDK_KEY_s,
	KEY_t								= GDK_KEY_t,
	KEY_u								= GDK_KEY_u,
	KEY_v								= GDK_KEY_v,
	KEY_w								= GDK_KEY_w,
	KEY_x								= GDK_KEY_x,
	KEY_y								= GDK_KEY_y,
	KEY_z								= GDK_KEY_z,
	KEY_F1							= GDK_KEY_F1,
	KEY_F2							= GDK_KEY_F2,
	KEY_F3							= GDK_KEY_F3,
	KEY_F4							= GDK_KEY_F4,
	KEY_F5							= GDK_KEY_F5,
	KEY_F6							= GDK_KEY_F6,
	KEY_F7							= GDK_KEY_F7,
	KEY_F8							= GDK_KEY_F8,
	KEY_F9							= GDK_KEY_F9,
	KEY_F10							= GDK_KEY_F10,
	KEY_F11							= GDK_KEY_F11,
	KEY_F12							= GDK_KEY_F12,
};


gboolean delete_event_callback(GtkWidget *widget,GtkWidget *event,gpointer data) {
//	WoTFrame *dlg = (WoTFrame *)data;
	app.handleAction(ACTION_QUIT);
	return FALSE;
}

void menuitem_callback(int code) {
app.printf("menuitem_callback(%d)",code);
	app.handleAction(code);
}

gboolean statusbar_push(GtkWidget *widget,GdkEventCrossing *ev,gpointer data) {
	app.handleAction(ACTION_SHOW_STATUS,0,(void *)g_object_get_data(G_OBJECT(widget),"StatusbarText"));
	return FALSE;
}

gboolean statusbar_pop(GtkWidget *widget,GdkEventCrossing *ev,gpointer data) {
	app.handleAction(ACTION_SHOW_STATUS,0);
	return FALSE;
}



MainFrame::MainFrame() : aApplication(APP_PROJECT),menu(),images(),surfaces(),occult() {
printf("MainFrame::MainFrame()");
	items = 0;
	profile_dlg = 0;
	planets_dlg = 0;
}

MainFrame::~MainFrame() {
printf("MainFrame::~MainFrame()");
	if(items) { free(items);items = 0; }
}

bool MainFrame::init(int argc,char *argv[]) {
printf("MainFrame::init()");
	const char *file;

	setUserAgent(APP_USER_AGENT);

	aHttp http(app);
	file = http.getf(WEB_HOST,WEB_PATH "files.php?t=%" PRIu64,(uint64_t)app_last_access);
app.printf("MainFrame::init(last_access=%" PRIu64 ")",(uint64_t)app_last_access);
	if(file && *file) {
fprintf(stderr,"%s",file);
fflush(stderr);
		aVector *files = new aVector();
		files->split(file,"\n");
		new InstallDlg(0,"Downloading files...",*this,*files);
	} else  this->init();
	return true;
}

void MainFrame::init() {
	const char *p;

	aApplication::init();
	TextPage::loadHistory();

	if((p=getProperty("local.user"))) strcpy(local_user,p);
	else *local_user = '\0';
	if((p=getProperty("local.password"))) strcpy(local_password,p);
	else *local_password = '\0';
	*local_key = '\0';

	gui.window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_window_set_title(GTK_WINDOW(gui.window),APP_TITLE);
	gtk_window_set_default_size(GTK_WINDOW(gui.window),900,600);
	gtk_widget_set_size_request(gui.window,780,540);
	gtk_window_set_resizable(GTK_WINDOW(gui.window),TRUE);
	gtk_window_set_position(GTK_WINDOW(gui.window),GTK_WIN_POS_CENTER);
/*
	{
		int i;
		const char **icons[] = { mantichora16_xpm,mantichora32_xpm,mantichora48_xpm,mantichora64_xpm };
		GList *iconlist = 0;
		GdkVisual *visual = gtk_widget_get_visual(gui.window);
		cairo_surface_t *s;
		cairo_t *cr;
		GdkPixmap *pixmap;
		GdkPixbuf *pixbuf;
		for(i=0; i<4; i++) {
			pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL,colormap,NULL,NULL,(gchar **)icons[i]);
			pixbuf = gdk_pixbuf_get_from_drawable(NULL,pixmap,NULL,0,0,0,0,-1,-1);
			pixbuf = gdk_pixbuf_get_from_surface(s,0,0,3,3);
			g_object_unref(pixmap);
			iconlist = g_list_append(iconlist,pixbuf);
		}
		gtk_window_set_default_icon_list(iconlist);
	}
*/
	GtkAccelGroup *accel_group = gtk_accel_group_new();
	gtk_window_add_accel_group(GTK_WINDOW(gui.window),accel_group);

	GtkWidget *vbox = gtk_vbox_new(FALSE,0);

	gui.statusbar = gtk_statusbar_new();
	gtk_box_pack_end(GTK_BOX(vbox),gui.statusbar,FALSE,FALSE,0);

	gui.menubar = gtk_menu_bar_new();
	{
		const menu_item menu_items[] = {
			{ NULL,"file",0,true,-1 },
				{ "file","new",ACTION_NEW,true,KEY_n,KEY_CONTROL_MASK },
				{ "file","open",ACTION_OPEN,true,KEY_o,KEY_CONTROL_MASK },
				{ "file","close",ACTION_CLOSE,true,KEY_w,KEY_CONTROL_MASK },
				{ "file","---" },
				{ "file","login",ACTION_LOGINOUT,true,-1 },
				{ "file","---" },
				{ "file","print",ACTION_PRINT,false,KEY_p,KEY_CONTROL_MASK },
				{ "file","preview",ACTION_PREVIEW,false,-1 },
				{ "file","---" },
				{ "file","quit",ACTION_QUIT,true,KEY_x,KEY_ALT_MASK },
			{ NULL,"astro",0,true,-1 },
				{ "astro","horoscope",ACTION_HOROSCOPE,true,KEY_n,KEY_CONTROL_MASK },
				{ "astro","herenow",ACTION_HERENOW,true,KEY_F2,0 },
				{ "astro","---" },
				{ "astro","natal",ACTION_NATAL,false,KEY_F3,0 },
				{ "astro","solar",ACTION_SOLAR,false,KEY_F4,0 },
				{ "astro","---" },
				{ "astro","synastry",ACTION_SYNASTRY,false,KEY_F5,0 },
				{ "astro","composit",ACTION_COMPOSIT,false,KEY_F6,0 },
				{ "astro","comsyn",ACTION_COMSYN,false,KEY_F7,0 },
				{ "astro","---" },
				{ "astro","astro_settings",0,true,-1 },
					{ "astro_settings","planets",ACTION_PLANETS,true,-1 },
					{ "astro_settings","aspects",ACTION_ASPECTS,false,-1 },
				{ "astro","---" },
				{ "astro","statistics",ACTION_STATISTICS,false,-1 },
				{ "astro","search",ACTION_SEARCH,false,KEY_f,KEY_CONTROL_MASK, },
			{ NULL,"occult",0,true,-1 },
				{ "occult","wordlist",ACTION_WORDLIST,true,-1 },
					{ "wordlist","terminology",ACTION_TERMINOLOGY,false,-1 },
					{ "wordlist","langs",ACTION_LANGS,false,-1 },
					{ "wordlist","symlex",ACTION_SYMLEX,false,-1 },
				{ "occult","translation",ACTION_TRANSLATION,false,-1 },
				{ "occult","gematria",ACTION_GEMATRIA,false,-1 },
				{ "occult","---" },
				{ "occult","alphabet",ACTION_ALPHABET,false,-1 },
				{ "occult","symbols",ACTION_SYMBOLS,false,-1 },
				{ "occult","correspondence",ACTION_CORRESPONDENCE,false,-1 },
				{ "occult","---" },
				{ "occult","qabalah",ACTION_QABALAH,false,-1 },
				{ "occult","enochian",ACTION_ENOCHIAN,false,-1 },
				{ "occult","alchemy",ACTION_ALCHEMY,false,-1 },
				{ "occult","---" },
				{ "occult","rituals",ACTION_RITUALS,false,-1 },
			{ NULL,"tarot",0,true,-1 },
				{ "tarot","tarotdecks",ACTION_TAROTDECKS,false,-1 },
				{ "tarot","tarotstars",ACTION_TAROTSTARS,false,-1 },
				{ "tarot","tarotdivination",ACTION_TAROTDIVINATION,true,KEY_d,KEY_CONTROL_MASK },
			{ NULL,"studies",0,true,-1 },
				{ "studies","journal",ACTION_JOURNAL,false,-1 },
				{ "studies","library",ACTION_LIBRARY,false,-1 },
				{ "studies","---" },
				{ "studies","classes",ACTION_CLASSES,false,-1 },
				{ "studies","messages",ACTION_MESSAGES,false,-1 },
				{ "studies","forum",ACTION_FORUM,false,-1 },
				{ "studies","chat",ACTION_CHAT,false,-1 },
			{ NULL,"help",0,true,-1 },
				{ "help","content",ACTION_CONTENT,false,KEY_F1,0 },
				{ "help","---" },
				{ "help","about",ACTION_ABOUT,false,-1 },
			{ NULL,NULL }
		};

		char str[256];
		int nitems = -1;
		while(menu_items[++nitems].id!=NULL);
app.printf("nitems=%d",nitems);
		items = (menu_item *)malloc(nitems*sizeof(menu_item));
		memcpy(items,menu_items,nitems*sizeof(menu_item));

		int i,j;
		menu_item *m,*mp;

		for(i=0; i<nitems; i++) {
			m = &items[i];
			m->index = i;
			m->lvl = 0;
			if(*m->id=='-' && !strcmp(m->id,"---")) m->name = 0,m->status = 0;
			else {
				m->name = getf("menu.%s",m->id);
				m->status = getf("menu.status.%s",m->id);
			}
			if(!m->name) m->name = m->id;
			if(m->pid) {
				for(j=0; j<i; j++) if(*items[j].id==*m->pid && !strcmp(&items[j].id[1],&m->pid[1])) {
					m->parent = &items[j];
					if(!items[j].child) items[j].child = m;
					break;
				}
			}
		}

		for(i=0; i<nitems; i++) {
			m = &items[i];
			if(m->parent) for(mp=m->parent,m->lvl=0; mp; mp=mp->parent) m->lvl++;
		}

		m = &items[0];
		for(i=0; m && i<nitems; i++) {
			*str = '\0';
			for(j=0; j<m->lvl; j++) strcat(str,"--> ");
			strcat(str,m->name);
app.printf("init(menu: index=%d,id='%s',parent='%s',child='%s',menuitem='%s')",m->index,m->id,m->parent? m->parent->id : "",m->child? m->child->id : "",str);

			if(*m->id=='-' && !strcmp(m->id,"---")) {
				if(m->parent) {
					m->item = gtk_separator_menu_item_new();
					gtk_menu_shell_append(GTK_MENU_SHELL(m->parent->submenu),m->item);
				}
			} else {
				m->item = gtk_image_menu_item_new_with_label(m->name);
				menu.put(m->code,m);
				if(!m->sensitive) gtk_widget_set_sensitive(m->item,false);
				if(m->acc!=-1) {
					gtk_image_menu_item_set_accel_group(GTK_IMAGE_MENU_ITEM(m->item),accel_group);
					gtk_widget_add_accelerator(m->item,"activate",accel_group,m->acc,(GdkModifierType)m->acc_mod,GTK_ACCEL_VISIBLE);
				}
				if(m->status) {
					g_object_set_data(G_OBJECT(m->item),"StatusbarText",(gpointer)m->status);
					g_signal_connect(m->item,"enter-notify-event",G_CALLBACK(statusbar_push),(gpointer)gui.statusbar);
					g_signal_connect(m->item,"leave-notify-event",G_CALLBACK(statusbar_pop),(gpointer)gui.statusbar);
				}
				if(m->child) {
					m->submenu = gtk_menu_new();
					gtk_menu_item_set_submenu(GTK_MENU_ITEM(m->item),m->submenu);
				}
				if(m->parent) {
					gtk_menu_shell_append(GTK_MENU_SHELL(m->parent->submenu),m->item);
					if(m->code) g_signal_connect(m->item,"activate",G_CALLBACK(menuitem_callback),(gpointer)m->code);
				} else {
					gtk_menu_shell_append(GTK_MENU_SHELL(gui.menubar),m->item);
				}
			}

			if(i==nitems-1) break;
			if(m->child) m = m->child;
			else if(items[m->index+1].parent==m->parent || m->parent) m = &items[m->index+1];
			/*else if(m->parent) {
app.printf("init(menu: next <--)");
				for(j=m->index+1,m=m->parent; m && items[j].parent!=m->parent; m=m->parent);
				if(m) {
					if(!m->parent && items[m->index+1].parent) break;
					m = &items[m->index+1];
				}
			}*/ else break;
		}
	}
	gtk_box_pack_start(GTK_BOX(vbox),gui.menubar,FALSE,FALSE,0);

	gui.notebook = gtk_notebook_new();
	gtk_notebook_set_tab_pos(GTK_NOTEBOOK(gui.notebook),GTK_POS_TOP);
	gtk_box_pack_start(GTK_BOX(vbox),gui.notebook,TRUE,TRUE,0);

	gtk_container_add(GTK_CONTAINER(gui.window),vbox);


	g_signal_connect(G_OBJECT(gui.window),"delete_event",G_CALLBACK(delete_event_callback),this);
	gtk_widget_show_all(gui.window);

	profile_dlg = new ProfileDlg(GTK_WINDOW(gui.window));
	planets_dlg = new PlanetsDlg(GTK_WINDOW(gui.window));

/*
	handleAction(ACTION_HERENOW);
	const char *keep = getProperty("login.keep");
	if(keep && (!strcmp(keep,"true") || !strcmp(keep,"1")) && *local_user && *local_password) handleAction(ACTION_LOGIN,1);
	else handleAction(ACTION_LOGINOUT);
*/
}

void MainFrame::exit() {
printf("MainFrame::exit()");
	while(closePage(0));
	saveProperties();
	TextPage::saveHistory();
	{
		GdkPixbuf *pixbuf;
		cairo_surface_t *surface;
		aHashtable::iterator iter;
		iter = images.iterate();
		while((pixbuf=(GdkPixbuf *)iter.next())) g_object_unref(pixbuf);
		iter = surfaces.iterate();
		while((surface=(cairo_surface_t *)iter.next())) cairo_surface_destroy(surface);
	}

	aApplication::exit();
}


int MainFrame::handleAction(int code,int p1,void *p2) {
	switch(code) {
		case ACTION_NEW:
		case ACTION_OPEN:
		case ACTION_HOROSCOPE:
			profile_dlg->clearForm();
			profile_dlg->show();
			break;
		case ACTION_CLOSE:closePage();break;
		case ACTION_LOGINOUT:
			if(*local_key=='\0') new LoginDlg(GTK_WINDOW(gui.window));
			else handleAction(ACTION_LOGOUT);
			break;
		case ACTION_PRINT:break;
		case ACTION_PREVIEW:break;
		case ACTION_QUIT:
			app.exit();
			gtk_main_quit();
			break;
		case ACTION_HERENOW:
		{
			Profile p;
			p.setName(app.get("hereandnow"));
			time_t t = time(0);
			struct tm *now = localtime(&t);
			p.setDate(1900+now->tm_year,now->tm_mon+1,now->tm_mday,now->tm_hour,now->tm_min,now->tm_sec,now->tm_isdst>0);
			p.setLocation("Europe/Stockholm",1.0,"18E03","59N21","Stockholm","EWNS");
			Horoscope *h = new Horoscope(&p);
			h->castNatalChart();
			new HoroscopeChartPage(h);
			break;
		}
		case ACTION_NATAL:break;
		case ACTION_SOLAR:break;
		case ACTION_SYNASTRY:break;
		case ACTION_COMPOSIT:break;
		case ACTION_COMSYN:break;
		case ACTION_PLANETS:
			planets_dlg->show();
			break;
		case ACTION_ASPECTS:break;
		case ACTION_STATISTICS:break;
		case ACTION_SEARCH:break;
		case ACTION_WORDLIST:break;
		case ACTION_TERMINOLOGY:break;
		case ACTION_LANGS:break;
		case ACTION_SYMLEX:break;
		case ACTION_TRANSLATION:break;
		case ACTION_GEMATRIA:break;
		case ACTION_ALPHABET:break;
		case ACTION_SYMBOLS:break;
		case ACTION_CORRESPONDENCE:break;
		case ACTION_QABALAH:break;
		case ACTION_ENOCHIAN:break;
		case ACTION_ALCHEMY:break;
		case ACTION_RITUALS:break;
		case ACTION_TAROTDECKS:break;
		case ACTION_TAROTSTARS:break;
		case ACTION_TAROTDIVINATION:
			new TarotDivinationDlg(GTK_WINDOW(gui.window));
			break;
		case ACTION_JOURNAL:break;
		case ACTION_LIBRARY:break;
		case ACTION_CLASSES:break;
		case ACTION_MESSAGES:break;
		case ACTION_FORUM:break;
		case ACTION_CHAT:break;
		case ACTION_CONTENT:break;
		case ACTION_ABOUT:break;

		case ACTION_SHOW_STATUS:
			if(p2) gtk_statusbar_push(GTK_STATUSBAR(gui.statusbar),p1,(gchar *)p2);
			else gtk_statusbar_pop(GTK_STATUSBAR(gui.statusbar),p1);
			break;
		case ACTION_LOGIN:
		{
			*local_key = '\0';
			if(!*local_user || !*local_password) break;
			aString user(local_user),password(local_password);
			user.encodeURL();
			password.encodeURL();
			aHttp http(app);
			const char *key = http.postf(WEB_HOST,WEB_PATH "login.php?u=%s&p=%s",user.toCharArray(),password.toCharArray());
			if(strncmp(key,"OK",2)!=0) {
				break;
			}
			setProperty("local.user",local_user);
			setProperty("local.password",local_password);
			setProperty("login.keep",p1? "true" : "false");
			strcpy(local_key,&key[3]);
			menu_item *m = (menu_item *)menu.get(ACTION_LOGINOUT);
			gtk_menu_item_set_label(GTK_MENU_ITEM(m->item),get("menu.logout"));
			break;
		}
		case ACTION_LOGOUT:
		{
			*local_key = '\0';
			setProperty("login.keep","false");
			menu_item *m = (menu_item *)menu.get(ACTION_LOGINOUT);
			gtk_menu_item_set_label(GTK_MENU_ITEM(m->item),get("menu.login"));
			break;
		}
	}
	return 1;
}


GdkPixbuf *MainFrame::getImage(const char *fn) {
   GdkPixbuf *image = (GdkPixbuf *)images.get(fn);
	if(!image) {
		image = loadImage(fn);
		images.put(fn,image);
	}
   return image;
}

GdkPixbuf *MainFrame::loadImage(const char *fn) {
	GdkPixbuf *image = 0;
	GError *error = 0;
	image = gdk_pixbuf_new_from_file(fn,&error);
	if(!image) {
		fprintf(stderr,"Create Pixbuf error: %s\n",error->message);
		g_error_free(error);
	}
	return image;
}

cairo_surface_t *MainFrame::getSurface(const char *fn) {
   cairo_surface_t *surface = (cairo_surface_t *)surfaces.get(fn);
	if(!surface) {
app.printf("MainFrame::getSurface(fn=%s)",fn);
		surface = cairo_image_surface_create_from_png(fn);
		surfaces.put(fn,surface);
	}
   return surface;
}

void MainFrame::setLanguage(const char *l) {
printf("MainFrame::loadLanguage(lang=%s)",l);
	aApplication::setLanguage(l);
	occult.load();
}

FILE *MainFrame::fopenlangf(char *path,const char *fn, ...) {
	FILE *fp = 0;
	char s1[64],s2[128];
	va_list args;
   va_start(args,fn);
	vsnprintf(s1,64,fn,args);
   va_end(args);
	sprintf(s2,"%slang/%s/%s",getHomeDir(),getLanguage(),s1);
	if(!(fp=fopen(s2,"r"))) {
		sprintf(s2,"%slang/en/%s",getHomeDir(),s1);
		fp = fopen(s2,"r");
	}
	if(path && fp) strcpy(path,s2);
	return fp;
}


void MainFrame::openPage(Page &page) {
printf("MainFrame::openPage(1)");
	gtk_widget_show_all(page.getTab());
	gtk_widget_show_all(page.getPage());
printf("MainFrame::openPage(2)");
	int index = gtk_notebook_append_page(GTK_NOTEBOOK(gui.notebook),page.getPage(),page.getTab());
	gtk_notebook_set_current_page(GTK_NOTEBOOK(gui.notebook),index);
printf("MainFrame::openPage(3)");
}

bool MainFrame::closePage(Page *page) {
	if(gtk_notebook_get_n_pages(GTK_NOTEBOOK(gui.notebook))==0) return false;
	int index = 0;
	if(!page) {
		index = gtk_notebook_get_current_page(GTK_NOTEBOOK(gui.notebook));
		GtkWidget *p = gtk_notebook_get_nth_page(GTK_NOTEBOOK(gui.notebook),index);
		page = (Page *)g_object_get_data(G_OBJECT(p),"PageObject");
	} else index = getPageIndex(*page);
	if(!page) return false;
	delete page;
	gtk_notebook_remove_page(GTK_NOTEBOOK(gui.notebook),index);
	return true;
}

int MainFrame::getPageIndex(Page &page) {
	return gtk_notebook_page_num(GTK_NOTEBOOK(gui.notebook),page.getPage());
}

